<template>
  <div class="tree-node">
    <div 
      :class="['node-content', getNodeTypeClass(node), { selected: selected === node }]"
    >
      <span 
        v-if="hasChildren" 
        @click="toggleExpanded" 
        class="expand-icon"
        :class="{ expanded: shouldExpand }"
      >
        {{ shouldExpand ? '▼' : '▶' }}
      </span>
      <span v-else class="expand-placeholder"></span>
      <span 
        @click="$emit('select', node)" 
        class="node-clickable"
        :class="{ matched: isMatched }"
      >
        <span class="node-icon">{{ getNodeIcon(node) }}</span>
        <span class="node-text">{{ getNodeDisplayText(node) }}</span>
      </span>
    </div>
    <div 
      v-if="hasChildren && shouldExpand" 
      class="node-children"
    >
      <TreeNode 
        v-for="(child, index) in node.children" 
        :key="index"
        :node="child"
        :selected="selected"
        :search-query="searchQuery"
        :search-matched-paths="searchMatchedPaths"
        @select="$emit('select', $event)"
      />
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref, computed } from 'vue';

export default defineComponent({
  name: 'TreeNode',
  props: {
    node: {
      type: Object,
      required: true
    },
    selected: {
      type: Object,
      default: null
    },
    searchQuery: {
      type: String,
      default: ''
    },
    searchMatchedPaths: {
      type: Object,
      default: () => new Set()
    }
  },
  emits: ['select'],
  setup(props, { emit }) {
    // 展开状态
    const isExpanded = ref(false);

    // 计算是否应该展开（基于搜索结果）
    const shouldExpand = computed(() => {
      if (!props.searchQuery || !props.searchMatchedPaths) {
        return isExpanded.value;
      }
      
      // 如果有搜索查询，检查当前节点路径是否在匹配路径中
      if (props.searchMatchedPaths.has(props.node.path)) {
        return true;
      }
      
      // 检查是否有子节点在匹配路径中
      if (props.node.children) {
        for (const child of props.node.children) {
          if (props.searchMatchedPaths.has(child.path)) {
            return true;
          }
        }
      }
      
      return false;
    });

    // 计算是否匹配搜索
    const isMatched = computed(() => {
      if (!props.searchQuery || !props.searchMatchedPaths) {
        return false;
      }
      return props.searchMatchedPaths.has(props.node.path);
    });

    // 计算是否有子节点
    const hasChildren = computed(() => {
      return props.node.children && props.node.children.length > 0;
    });

    // 切换展开状态
    function toggleExpanded() {
      isExpanded.value = !isExpanded.value;
    }

    // 获取节点显示文本
    function getNodeDisplayText(node: any): string {
      if (node.type === "object") {
        const childCount = node.children?.length || 0;
        return `${node.key} {${childCount} 个属性}`;
      } else if (node.type === "array") {
        return `${node.key} [${node.length} 个元素]`;
      } else {
        return `${node.key}: ${JSON.stringify(node.value)}`;
      }
    }

    // 获取节点类型样式
    function getNodeTypeClass(node: any): string {
      return `node-${node.type}`;
    }

    // 获取节点图标
    function getNodeIcon(node: any): string {
      const icons: Record<string, string> = {
        object: '📁',
        array: '📋',
        string: '📝',
        number: '🔢',
        boolean: '✅',
        null: '❌'
      };
      return icons[node.type] || '📄';
    }

    return {
      isExpanded,
      shouldExpand,
      isMatched,
      hasChildren,
      toggleExpanded,
      getNodeDisplayText,
      getNodeTypeClass,
      getNodeIcon
    };
  }
});
</script>

<style scoped>
.tree-node {
  margin-left: 0;
}

.node-content {
  display: flex;
  align-items: center;
  padding: 4px 8px;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.2s;
}

.node-content:hover {
  background-color: #f5f5f5;
}

.node-content.selected {
  background-color: #e3f2fd;
}

.expand-icon {
  width: 16px;
  height: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-right: 4px;
  cursor: pointer;
  user-select: none;
  transition: transform 0.2s;
}

.expand-icon:hover {
  background-color: #e0e0e0;
  border-radius: 2px;
}

.expand-placeholder {
  width: 16px;
  margin-right: 4px;
}

.node-clickable {
  display: flex;
  align-items: center;
  flex: 1;
  cursor: pointer;
}

.node-icon {
  margin-right: 6px;
  font-size: 14px;
}

.node-text {
  font-family: 'Courier New', monospace;
  font-size: 13px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.node-children {
  margin-left: 20px;
  border-left: 1px dashed #ddd;
  padding-left: 8px;
}

/* 节点类型样式 */
.node-object .node-text {
  color: #1976d2;
  font-weight: 500;
}

.node-array .node-text {
  color: #388e3c;
  font-weight: 500;
}

.node-string .node-text {
  color: #f57c00;
}

.node-number .node-text {
  color: #7b1fa2;
}

.node-boolean .node-text {
  color: #d32f2f;
}

.node-null .node-text {
  color: #616161;
  font-style: italic;
}

/* 搜索匹配高亮样式 */
.node-clickable.matched {
  background-color: #fff3cd;
  border: 1px solid #ffeaa7;
  border-radius: 4px;
  padding: 2px 4px;
  margin: -2px -4px;
}

.node-clickable.matched .node-text {
  font-weight: 600;
  color: #856404;
}
</style>